package org.example.ssh.base

import kotlinx.io.IOException
import net.schmizz.sshj.SSHClient
import net.schmizz.sshj.sftp.FileAttributes
import net.schmizz.sshj.sftp.FileMode
import net.schmizz.sshj.sftp.SFTPClient
import java.io.File

class SSHUtils {
}

fun executeCmd(ssh: SSHClient, command: String): String {
    val session = ssh.startSession()
    try {
        val cmd = session.exec(command)
        val output = cmd.inputStream.bufferedReader().readText()
        cmd.join() // 等待完成
        if (cmd.exitStatus != 0) {

            throw RuntimeException("""
                Command failed: $command, exit code: ${cmd.exitStatus} ;exitErrorMessage:${cmd.exitErrorMessage} \n
                ;errorStream:${cmd.errorStream.bufferedReader().readText()}
            """.trimIndent())
        }
        return output
    } finally {
        session.close()
    }
}

fun executeCmdPrint(ssh: SSHClient, command: String): String {
    val res = executeCmd(ssh, command)
    println(res)
    return res
}

/**
 * 递归上传本地文件夹到远程 SFTP 服务器
 * @param sftp SFTPClient 实例
 * @param localDir 本地文件夹路径
 * @param remoteDir 远程目标路径（根目录）
 */
fun uploadDirectoryRecursive(
    sftp: SFTPClient,
    localDir: String,
    remoteDir: String
) {
    val localFile = File(localDir)
    if (!localFile.exists()) {
        throw IllegalArgumentException("Local directory does not exist: $localDir")
    }

    // 确保远程父目录存在（递归创建）
    mkdirs(sftp, remoteDir)

    // 开始递归上传
    doUpload(sftp, localFile, remoteDir)
}

// 递归处理
private fun doUpload(sftp: SFTPClient, localFile: File, remoteBasePath: String) {
    val remotePath = if (remoteBasePath == "/") "/${localFile.name}" else "$remoteBasePath/${localFile.name}"

    if (localFile.isDirectory) {
        // 创建远程目录
        try {
            sftp.mkdir(remotePath)
            println("Created directory: $remotePath")
        } catch (e: Exception) {
            println("Warning: Could not create directory (may already exist): $remotePath | ${e.message}")
        }

        // 递归上传子文件
        localFile.listFiles()?.forEach { child ->
            doUpload(sftp, child, remotePath)
        }
    } else {
        // 是文件，直接上传
        sftp.put(localFile.absolutePath, remotePath)
        println("Uploaded file: ${localFile.absolutePath} -> $remotePath")
    }
}

/**
 * 递归创建远程目录（类似 mkdir -p）
 */
fun mkdirs(sftp: SFTPClient, remotePath: String) {
    val parts = remotePath
        .split("/")
        .filter { it.isNotBlank() }

    var current = ""
    for (part in parts) {
        current = if (current.isEmpty()) "/$part" else "$current/$part"
        try {
            if (isDirectory(sftp, current)) continue
            sftp.mkdir(current)
            println("Created directory: $current")
        } catch (e: Exception) {
            // 忽略已存在等非致命错误
            if (!e.message.orEmpty().contains("already exists", ignoreCase = true)) {
                throw RuntimeException("Failed to create remote directory: $current", e)
            }
        }
    }
}


fun deleteDirectoryRecursive(sftp: SFTPClient, path: String) {
    try {
        val attrs = sftp.stat(path)
        if (attrs.type != FileMode.Type.DIRECTORY) {
            // 如果是文件，直接删除
            sftp.rm(path)
            println("Deleted file: $path")
            return
        }

        // 如果是目录，遍历内容并递归删除
        sftp.ls(path).forEach { entry ->
            val entryName = entry.name
            // 跳过 . 和 ..
            if (entryName == "." || entryName == "..") return@forEach

            val fullPath = if (path.endsWith("/")) "$path$entryName" else "$path/$entryName"

            when {
                entry.attributes.type == FileMode.Type.DIRECTORY -> {
                    deleteDirectoryRecursive(sftp, fullPath)
                }
                else -> {
                    sftp.rm(fullPath)
                    println("Deleted file: $fullPath")
                }
            }
        }

        // 最后删除空目录
        sftp.rmdir(path)
        println("Deleted directory: $path")

    } catch (e: Exception) {
        if (e.message?.contains("No such file") == true) {
            println("Path does not exist (already deleted?): $path")
        } else {
            throw RuntimeException("Failed to delete path: $path", e)
        }
    }
}

fun exists(sftp: SFTPClient, path: String): Boolean {
    return try {
        val attrs: FileAttributes = sftp.stat(path)
        true // 能获取到属性，说明存在
    } catch (e: IOException) {
        false // 抛出异常（通常是 NoSuchFileException），说明不存在
    }
}

fun isDirectory(sftp: SFTPClient, path: String): Boolean {
    return try {
        val attrs: FileAttributes = sftp.stat(path)
        attrs.type == FileMode.Type.DIRECTORY
    } catch (e: IOException) {
        false
    }
}

fun isFile(sftp: SFTPClient, path: String): Boolean {
    return try {
        val attrs: FileAttributes = sftp.stat(path)
        attrs.type == FileMode.Type.REGULAR
    } catch (e: IOException) {
        false
    }
}


